#pragma once


#include <iostream>
#include <unistd.h>
#include <sys/epoll.h>
#include "Common.hpp"
#include "Log.hpp"

using namespace LogModule;

const static int gdefaultepfd = -1;

class Epoller
{
public:
    Epoller()
    :_epfd(gdefaultepfd)
    {}

    // 创建epoll模型
    void Init()
    {
        _epfd = epoll_create(256);
        if (_epfd < 0)
        {
            LOG(LogLevel::ERROR) << "epoll_create error";
            exit(EPOLL_CREATE_ERR);
        }
        LOG(LogLevel::INFO) << "epoll_create success, epfd: " << _epfd;
    }

    // epoll_wait等待事件就绪
    int Wait(struct epoll_event revs[], int rnum, int timeout)
    {
        int n = epoll_wait(_epfd, revs, rnum, timeout);
        if (n < 0)
        {
            LOG(LogLevel::WARNING) << "epoll_wait error";
            return n;
        }
        return n;
    }

    // Ctrl用于控制，对epoll模型进行添加或修改操作
    void Ctrl(int sockfd, uint32_t events, int flags)
    {
        struct epoll_event ev;
        ev.data.fd = sockfd;
        ev.events = events;
        int n = epoll_ctl(_epfd, flags, sockfd, &ev);
        if (n < 0)
        {
            LOG(LogLevel::WARNING) << "epoll_ctl error";
            return;
        }
    }

    void Add(int sockfd, uint32_t events)
    {
        Ctrl(sockfd, events, EPOLL_CTL_ADD);
    }

    void Update(int sockfd, uint32_t events)
    {
        Ctrl(sockfd, events, EPOLL_CTL_MOD);
    }

    // 删除epoll模型中对该fd的关心
    void Delete(int sockfd)
    {
        int n = epoll_ctl(_epfd, EPOLL_CTL_DEL, sockfd, nullptr);
        if (n < 0)
        {
            LOG(LogLevel::WARNING) << "epoll_ctl error";
        }
    }

    ~Epoller()
    {
        if (_epfd >= 0)
            close(_epfd);
    }
private:
    int _epfd;
};